#ifndef _ENGINEBSP_H
#define _ENGINEBSP_H

#include "..\common\types.h"
#include "..\common\def.h"
#include "..\common\string.h"
#include "..\common\arraylist.hpp"
#include "..\math\matrix.h"
#include "..\math\vector.h"
#include "..\math\plane.h"
#include "..\math\sphere.h"
#include "..\render\d3d_util.h"
#include "object.h"

struct D3DModel; 
class CActor;
class CD3D9Device;
class CDSound9Device;
class CDInput9Device;
class CPhysics;
#define _DEBUG_SHOWBSPSTATS

class EE_EXPORT CBSP : public CObject
{
	friend class CEngine; 

#define NODE_ID 0
#define LEFTCHILD_ID 1
#define RIGHTCHILD_ID 2

	struct NodeData {
		short id[3];
		Planef splitPlane;
		Spheref boundSphere;
	};
	struct LeafData {
		short id;
		D3DModel* pModel;
	};

	struct INode
	{
		uint id;
		ArrayList<CObject*> objects;

		INode() : id(-1)
		{	}

		virtual bool IsVisible(ViewOrrientation* view) = 0;
		virtual void Draw(ViewOrrientation* view) = 0;
		virtual void InsertObject(CObject* pObject) = 0;
	};

	struct Leaf : public INode
	{
		D3DModel* m_pMesh;

		Leaf() : INode()
		{	
			m_pMesh = NULL;
		}

		inline bool IsVisible(ViewOrrientation* view);
		inline void Draw(ViewOrrientation* view);
		inline void InsertObject(CObject* pObject);
	};

	struct Node : public INode
	{
		Spheref m_BoundSphere;
		Planef m_splitPlane;
		INode *m_pLeftChild;
		INode *m_pRightChild;

		Node() : INode()
		{	
			m_pRightChild = NULL;
			m_pLeftChild = NULL;  
		}

		inline bool IsVisible(ViewOrrientation* view);
		inline void Draw(ViewOrrientation* view);
		inline void InsertObject(CObject* pObject);
	};

	struct ConstructDatum
	{
		Node* m_pNode;
		uint m_leftChildID;
		uint m_rightChildID;

		ConstructDatum() : m_pNode(NULL), m_leftChildID(0), m_rightChildID(0)
		{	}

		ConstructDatum(Node* pNode, uint leftChildID, uint rightChildID) : m_pNode(pNode), m_leftChildID(leftChildID), m_rightChildID(rightChildID)
		{	}
	};

	ArrayList<ConstructDatum> m_Nodes;
	ArrayList<Leaf*> m_Leaves;
	INode* m_pRoot;
protected:

	void AttachNode(const NodeData& innerNode);
	void AttachLeaf(const LeafData& leaf);
public:
	CBSP(void); 
	virtual ~CBSP(void);
	void Draw(ViewOrrientation* pView);
	void InsertObject(CObject* pObject);
	void InsertRootObject(CObject* pObject);
}; 
#endif
